﻿using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using Newtonsoft.Json;
using T.ServiceComponent.Database.Service;
using T.FAS.Runtime.DataModel.Dao;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.ServiceComponent.Error;
//using T.FAS.Authority.MetaData.Dev.Plugin;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.DataModel.Dao
{
    public class DataQueryLogic
    {
        public const string MetaDataID = DataModelConst.DQMetaType;
        public const string MetaDataName = "数据查询";
        private readonly DataObjectLogic _dataObjectDao = new DataObjectLogic();
        private readonly DataQueryELBDao _dataQueryDao = new DataQueryELBDao();
        private readonly DataQueryColumnELBDao _dataQueryColumnELBDao = new DataQueryColumnELBDao();
        //private readonly ActionPermissionDefinitionManager _permissionMgr = new ActionPermissionDefinitionManager();

        #region 查询元数据信息
        /// <summary>
        /// 获取DQ byID
        /// </summary>
        /// <param name="dqID"></param>
        /// <param name="isSubQuery">是否子查询，防止堆栈溢出</param>
        /// <returns></returns>
        public DataQuery GetDataQueryByID(string dqID, bool isSubQuery = false)
        {
            var dataquery = _dataQueryDao.GetDataQueryByID(dqID);
            //PackagingDependencyMetaData(dataquery, isSubQuery);
            //Repair(dataquery);
            return dataquery;
        }

        /// <summary>
        /// 获取DQ集合
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public List<DataQuery> GetDataQuerys(Dictionary<string, string> filter)
        {
            var dqlist = _dataQueryDao.GetDataQuerys(filter);
            foreach (var dq in dqlist)
            {
                PackagingDependencyMetaData(dq);
            }
            return dqlist;
        }

        /// <summary>
        /// 初始化填充DQ的引用类型属性
        /// </summary>
        /// <param name="dq"></param>
        public void PackagingDependencyMetaData(DataQuery dq, bool isSubQuery = false)
        {
            if (dq == null)
                return;
            var unifyCode = DataModelErrorCode.GetUnifiedErrorCode(MetaDataID, dq.ID, dq.Code);
            try
            {
                //为datasource填充DO实例
                foreach (var source in dq.DataQuerySources)
                {
                    if (source.DataObject == null)  //兼容json反序列化处理，如果source.DataObject不为空，则为反序列化出来的DO，直接处理即可
                        source.DataObject = _dataObjectDao.GetDataObjectByID(source.DataObjectID);
                    if (source.DataObject == null)
                        throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}获取dataObject:{source.DataObjectID}实体失败，请检查！");
                }
                var dqSources = dq.DataQuerySources.Select(s => s.DataObject).ToList();
                //为datacolumn填充实例
                foreach (var column in dq.DataQueryColumns)
                {
                    if (column.ColumnType == ColumnType.Normal)
                    {
                        column.DataObject = dqSources.Find(o => o.ID == column.DataObjectID);
                        column.DataColumn = column.DataObject.Columns.Find(col => col.ID == column.DataObjectColumnID);
                    }
                    else
                    {
                        //聚合列也需要填充DO及列信息
                        if (!string.IsNullOrEmpty(column.DataObjectID))
                        {
                            column.DataObject = dqSources.Find(o => o.ID == column.DataObjectID);
                            column.DataColumn = column.DataObject.Columns.Find(col => col.ID == column.DataObjectColumnID);
                        }
                    }
                    if (!string.IsNullOrEmpty(column.DataObjectID))
                    {
                        if (column.DataObject == null)
                        {
                            throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}的列:{column.Name}获取dataObject实体失败，请检查！");
                        }
                        //if (column.DataColumn == null)
                        //{
                        //    throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}的列:{column.Name}获取dataObject:{column.DataObject.Code}对应的列为空，请检查！");
                        //}
                    }
                }
                //为datasort填充实例
                if (dq.DataQuerySorts != null)
                {
                    foreach (var sort in dq.DataQuerySorts.Where(s => s.SortItemType == 0))
                    {
                        //如何判断sort列为自定义列，当SortItemType：0 且 DataObjectID为空时
                        if (!string.IsNullOrEmpty(sort.DataObjectID))
                        {
                            sort.DataObject = dqSources.Find(o => o.ID == sort.DataObjectID);
                            sort.DataColumn = sort.DataObject.Columns.Find(col => col.ID == sort.DataObjectColumnID);
                        }
                        else if (!string.IsNullOrEmpty(sort.DataQueryColumnID))
                        {
                            sort.DataQueryColumn = dq.DataQueryColumns.Find(c => c.ID == sort.DataQueryColumnID);
                        }
                    }
                }
                //填充Join实例
                if (dq.DataQueryJoins != null)
                {
                    foreach (var join in dq.DataQueryJoins)
                    {
                        join.LeftQuerySource = dq.DataQuerySources.Find(s => s.ID == join.LeftSourceID);
                        join.RightQuerySource = dq.DataQuerySources.Find(s => s.ID == join.RightSourceID);
                    }
                }
                if (dq.SubQuerys != null)
                {
                    //填充subquery实例
                    foreach (var subquery in dq.SubQuerys)
                    {
                        if (isSubQuery) //子查询DQ不处理SubQuery，否则出现循环引用时会引起堆栈溢出
                            break;
                        //注意不要引起堆栈溢出
                        if (!string.IsNullOrEmpty(subquery.SubQueryID))
                        {
                            subquery.SubQuery = GetDataQueryByID(subquery.SubQueryID, true);
                            if (subquery.SubQuery == null)
                            {
                                LocalLogService.Write($"{unifyCode}初始化时未找到子查询:{subquery.SubQueryID}的实例，请检查当前是否是导入操作。如果为运行时，此为异常场景 请检查");
                                //throw new FasException(DataModelErrorCode.DQ.RetrieveError, $"{MetaDataName}DQ:{dataquery.ID}获取子查询:{subquery.SubQueryID}实例时失败，请检查");
                            }
                        }
                    }
                }
                /* Todo
                if (dq.IsPermissionControl) //兼容json反序列化处理，如果ActionPermission不为空，则为反序列化出来的DQ，直接处理即可
                {
                    if (dq.ActionPermission == null)
                        dq.ActionPermission = _permissionMgr.GetActionPermissionDefinition(dq.ID);
                }*/
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}初始化失败，请检查！", e);
            }
        }

        #endregion

        #region 新增
        public void SaveDataQuery(DataQuery dataQuery)
        {
            ProcessSystemFields(dataQuery);

            try
            {
                _dataQueryDao.SaveDataQuery(dataQuery);
                /* Todo
                //如果启用权限控制，并设置了权限控制的信息，则进行权限数据的更新
                //否则执行删除操作
                if (dataQuery.IsPermissionControl && dataQuery.ActionPermission != null)
                    _permissionMgr.AddOrUpdate(dataQuery.ActionPermission);
                else
                    _permissionMgr.DeleteByActionId(dataQuery.ID);
                */

            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.CreateError, $"{MetaDataName}元数据保存失败", e);
            }
        }

        public void BatchSaveDataQuery(List<DataQuery> dataQueries)
        {
            if (dataQueries == null || dataQueries.Count == 0) return;
            foreach (var dataQuery in dataQueries)
            {
                ProcessSystemFields(dataQuery);

                ////如果启用权限控制，并设置了权限控制的信息，则进行权限数据的更新
                ////否则执行删除操作
                //if (dataQuery.IsPermissionControl && dataQuery.ActionPermission != null)
                //    _permissionMgr.AddOrUpdate(dataQuery.ActionPermission);
                //else
                //    _permissionMgr.DeleteByActionId(dataQuery.ID);
            }
            try
            {
                _dataQueryDao.BatchSaveDataQuery(dataQueries);
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.CreateError, $"{MetaDataName}元数据保存失败", e);
            }
        }

        #endregion

        #region 删除
        /// <summary>
        /// 删除DQ
        /// </summary>
        /// <param name="dqID"></param>
        public void DeleteDataQuery(string dqID)
        {
            try
            {
                _dataQueryDao.DeleteDataQuery(dqID);
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.DeleteError, $"{MetaDataName}元数据删除失败", e);
            }
        }

        /// <summary>
        /// 批量删除DQ
        /// </summary>
        /// <param name="dqIds"></param>
        public void BatchDeleteDataQuery(List<string> dqIds)
        {
            try
            {
                _dataQueryDao.BatchDeleteDataQuery(dqIds);
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.DeleteError, $"{MetaDataName}元数据删除失败", e);
            }
        }
        #endregion

        #region 修改
        /// <summary>
        /// 修改DQ元数据
        /// </summary>
        /// <param name="metaData"></param>
        public void Update(DataQuery metaData)
        {
            try
            {
                this.DeleteDataQuery(metaData.ID);
                this.SaveDataQuery(metaData);
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.UpdateError, $"{MetaDataName}元数据修改失败!", e);
            }
        }
        #endregion

        #region 修复
        /// <summary>
        /// 修复DQ
        /// 暂时只考虑修复DQ列找不到对应DO列的情况
        /// </summary>
        /// <param name="dqID"></param>
        public void Repair(string dqID)
        {
            var dataQuery = this.GetDataQueryByID(dqID);
            Repair(dataQuery);
        }

        /// <summary>
        /// 修复DQ
        /// 暂时只考虑修复DQ列找不到对应DO列的情况
        /// </summary>
        /// <param name="DataQueryID"></param>
        public void Repair(DataQuery dataQuery)
        {
            try
            {
                //找出DO中已经删掉的列，同步删除DQ字段
                var dropColumns = dataQuery.DataQueryColumns?.Where(col => !string.IsNullOrEmpty(col.DataObjectID) && col.DataColumn == null);
                var dropColumnIDs = dropColumns?.Select(col => col.ID)
                                               ?.ToList();
                if (dropColumnIDs != null && dropColumnIDs.Count > 0)
                {
                    //在DQ实例中删除字段
                    dataQuery.DataQueryColumns.RemoveAll(col => dropColumnIDs.Contains(col.ID));
                    //在库中删除字段，还是前端同一点保存生效？
                    _dataQueryColumnELBDao.Delete(dropColumnIDs);
                }

                //主DQ的DO新增列时自动同步
                var mainSource = dataQuery.DataQuerySources.FirstOrDefault(s => s.IsMainSource);
                var mainQuerySourceColumns = dataQuery.DataQueryColumns.Where(col => col.DataQuerySourceID == mainSource.ID);
                var mainQuerySourceColumnIDs = mainQuerySourceColumns.Select(col => col.DataObjectColumnID);
                //待新增的列
                var needAddColumns = mainSource.DataObject.Columns.Where(dqcol => !mainQuerySourceColumnIDs.Contains(dqcol.ID));
                List<DataQueryColumn> dqAddCols = new List<DataQueryColumn>();
                foreach (var addCol in needAddColumns)
                {
                    DataQueryColumn column = new DataQueryColumn
                    {
                        ID = Guid.NewGuid().ToString(),
                        DataQueryID = dataQuery.ID,
                        DataQuerySourceID = mainSource.ID,
                        DataObjectID = mainSource.DataObjectID,
                        DataObjectColumnID = addCol.ID,
                        Name = addCol.ColumnName,
                        Alias = addCol.ColumnName,            //主节点DQ.Column列名不加DO.Code前缀
                        DisplayName = addCol.DisplayName,     //主节点的列不加DO名
                        ColumnType = ColumnType.Normal,
                        ColumnDataType = addCol.ApplicationDataType,
                        IsHide = false,
                        DataColumn = addCol,
                        Sort = addCol.ColumnOrder,
                        Creator = dataQuery.Creator,
                        CreateTime = dataQuery.CreateTime,
                        LastModifyTime = dataQuery.LastModifyTime,
                        LastModifier = dataQuery.LastModifier,
                    };
                    dqAddCols.Add(column);
                }
                //在DQ对象实例中添加列
                dataQuery.DataQueryColumns.AddRange(dqAddCols);

                //在库中添加字段
                _dataQueryColumnELBDao.Add(dqAddCols);

                //主DQ的DO修改列名时自动同步
                var notMatchColumns = dataQuery.DataQueryColumns?.Where(col => !string.IsNullOrEmpty(col.DataObjectID) && col.DataColumn.ColumnName != col.Name);
                foreach (var item in notMatchColumns)
                {
                    item.Name = item.DataColumn.ColumnName;
                    item.Alias = item.DataColumn.ColumnName;
                    item.DisplayName = item.DataColumn.DisplayName;
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.RepairError, $"尝试修复DQ:{dataQuery?.ID}失败, Msg:{e.Message}", e);
            }
        }

        #endregion

        #region Private Funcs
        private static void ProcessSystemFields(DataQuery dataQuery)
        {
            EntityTools.FillMainObjectFieldForAdd(dataQuery, dataQuery);
            //处理Source，给系统默认字段赋值
            if (dataQuery.DataQuerySources != null && dataQuery.DataQuerySources.Count > 0)
            {
                dataQuery.DataQuerySources.ForEach(source =>
                {
                    source.DataQueryID = dataQuery.ID;
                    EntityTools.FillSystemFiledForAdd(source, dataQuery);
                });
            }
            //处理Joins，给系统默认字段赋值
            if (dataQuery.DataQueryJoins != null && dataQuery.DataQueryJoins.Count > 0)
            {
                dataQuery.DataQueryJoins.ForEach(join =>
                {
                    join.DataQueryID = dataQuery.ID;
                    EntityTools.FillSystemFiledForAdd(join, dataQuery);
                });
            }
            //处理Columns，给系统默认字段赋值
            if (dataQuery.DataQueryColumns != null && dataQuery.DataQueryColumns.Count > 0)
            {
                dataQuery.DataQueryColumns.ForEach(col =>
                {
                    col.DataQueryID = dataQuery.ID;
                    EntityTools.FillSystemFiledForAdd(col, dataQuery);
                });
            }
            //处理Filter，给系统默认字段赋值
            if (dataQuery.DataQueryFilters != null && dataQuery.DataQueryFilters.Count > 0)
            {
                dataQuery.DataQueryFilters.ForEach(filter =>
                {
                    filter.DataQueryID = dataQuery.ID;
                    EntityTools.FillSystemFiledForAdd(filter, dataQuery);
                });
            }
            //处理Sort，给系统默认字段赋值
            if (dataQuery.DataQuerySorts != null && dataQuery.DataQuerySorts.Count > 0)
            {
                dataQuery.DataQuerySorts.ForEach(sort =>
                {
                    sort.DataQueryID = dataQuery.ID;
                    EntityTools.FillSystemFiledForAdd(sort, dataQuery);
                });
            }
            //处理Param，给系统默认字段赋值
            if (dataQuery.DataQueryParams != null && dataQuery.DataQueryParams.Count > 0)
            {
                dataQuery.DataQueryParams.ForEach(param =>
                {
                    param.DataQueryID = dataQuery.ID;
                    EntityTools.FillSystemFiledForAdd(param, dataQuery);
                });
            }
            //处理Param，给系统默认字段赋值
            if (dataQuery.SubQuerys != null && dataQuery.SubQuerys.Count > 0)
            {
                dataQuery.SubQuerys.ForEach(sub =>
                {
                    sub.DataQueryID = dataQuery.ID;
                    EntityTools.FillSystemFiledForAdd(sub, dataQuery);
                });
            }
        }

        #endregion
    }
}